﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Nature.Toolkit.GKin
{
    public abstract class StatePostUpdateChemReactorController : IdealGasMixtureTimeController
    {
        public const int MaximumAdvanceAttempt = 100;

        protected abstract double AdvanceChemicalComposition();

        protected abstract bool ValidateStateChange();

        protected abstract IIdealGasMixtureTransform GetStatePostUpdateTransform();

        private int m_advanceAttempt = 0;
        private IIdealGasMixtureTransform m_statePostUpdateTransform;

        protected sealed override double Advance()
        {
            if (m_advanceAttempt == 0)
            {
                m_statePostUpdateTransform = GetStatePostUpdateTransform();
            }
            double dt = AdvanceChemicalComposition();            
            m_statePostUpdateTransform.Transform(Mixture);
            if (ValidateStateChange())
            {
                base.Commit();
                m_advanceAttempt = 0;
                m_statePostUpdateTransform = null;
                return dt;
            }
            else if (m_advanceAttempt++ < MaximumAdvanceAttempt)
            {
                base.Rollback();
                base.ProposeNextTimeIncrement(dt / 2.0);
                dt = Advance();
                return dt;
            }
            else 
            {
                m_advanceAttempt = 0;
                throw new InvalidOperationException("Failed to advance the ideal gas mixture state");
            }
        }
    }
}
